中间件概念
概述
在 Express.js 中,中间件是一个非常重要的概念。它允许你在请求到达最终路由处理程序之前或之后执行一些操作。中间件可以用于日志记录、身份验证、错误处理、数据处理等多种场景。理解中间件的工作原理和如何使用它们是掌握 Express.js 的关键。
什么是中间件?
中间件是一个函数,它可以访问请求对象 (req)、响应对象 (res) 以及应用程序的请求-响应周期中的下一个中间件函数 (next)。中间件函数可以执行以下任务:
- 执行任何代码。
- 修改请求和响应对象。
- 结束请求-响应周期。
- 调用堆栈中的下一个中间件。
如果当前中间件没有结束请求-响应周期,它必须调用 next() 将控制权传递给下一个中间件,否则请求将被挂起。
中间件的类型
在 Express.js 中,中间件可以分为以下几种类型:
- 应用级中间件:绑定到
app对象的中间件,使用app.use()或app.METHOD()方法。 - 路由级中间件:绑定到
express.Router()实例的中间件。 - 错误处理中间件:专门处理错误的中间件,具有四个参数
(err, req, res, next)。 - 内置中间件:Express.js 自带的中间件,如
express.static。 - 第三方中间件:由社区提供的中间件,如
body-parser。
应用级中间件
应用级中间件绑定到 app 对象,使用 app.use() 或 app.METHOD() 方法。以下是一个简单的例子:
const express = require('express');
const app = express();
// 应用级中间件
app.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
在这个例子中,app.use() 定义了一个中间件,它会在每个请求到达时记录当前时间。next() 函数将控制权传递给下一个中间件或路由处理程序。
路由级中间件
路由级中间件绑定到 express.Router() 实例。以下是一个例子:
const express = require('express');
const app = express();
const router = express.Router();
// 路由级中间件
router.use((req, res, next) => {
console.log('Request URL:', req.originalUrl);
next();
});
router.get('/', (req, res) => {
res.send('Hello Router!');
});
app.use('/router', router);
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
在这个例子中,router.use() 定义了一个中间件,它会在访问 /router 路径下的任何路由时记录请求的 URL。
错误处理中间件
错误处理中间件具有四个参数 (err, req, res, next)。它用于捕获和处理应用程序中的错误。以下是一个例子:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
throw new Error('Something went wrong!');
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
在这个例子中,当访问 / 路径时,会抛出一个错误。错误处理中间件会捕获这个错误并返回一个 500 状态码的响应。
内置中间件
Express.js 提供了一些内置中间件,如 express.static,用于提供静态文件服务。以下是一个例子:
const express = require('express');
const app = express();
// 内置中间件
app.use(express.static('public'));
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
在这个例子中,express.static 中间件用于提供 public 目录下的静态文件。
第三方中间件
第三方中间件由社区提供,可以扩展 Express.js 的功能。例如,body-parser 中间件用于解析请求体。以下是一个例子:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
// 第三方中间件
app.use(bodyParser.json());
app.post('/submit', (req, res) => {
res.json(req.body);
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
在这个例子中,body-parser 中间件用于解析 JSON 格式的请求体。
实践练习
练习 1:创建一个日志记录中间件
创建一个中间件,记录每个请求的 URL 和时间戳。
const express = require('express');
const app = express();
// 日志记录中间件
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next();
});
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
练习 2:创建一个错误处理中间件
创建一个错误处理中间件,捕获并处理应用程序中的错误。
const express = require('express');
const app = express();
app.get('/', (req, res) => {
throw new Error('Something went wrong!');
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
练习 3:使用第三方中间件
使用 cookie-parser 中间件解析请求中的 cookie。
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
// 使用第三方中间件
app.use(cookieParser());
app.get('/', (req, res) => {
res.send(`Cookies: ${JSON.stringify(req.cookies)}`);
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
总结
中间件是 Express.js 的核心概念之一,它允许你在请求到达最终路由处理程序之前或之后执行一些操作。通过理解和掌握中间件的使用,你可以构建更加灵活和强大的 Express.js 应用程序。希望这篇教程能帮助你更好地理解中间件的概念和使用方法。